#!/usr/bin/perl

package CommandRunner;

use strict;
use warnings;

use Utils qw(dd kebab_to_camel is_array);
use Log;

require Commands::BaseCommand;

# 挂载命令
my @commands = ();

sub mountCommand
{
    my $input = shift;
    if (is_array($input)) {
        push @commands, @{$input};
    } elsif (ref $input eq 'HASH') {
        push @commands, $input;
    }
}


sub execute {
    my $module_action = shift;
    my @args = @_;
    unless (defined $module_action) {
        Log::error("No command specified");
        usage();
        return;
    }

    my @module_action_arr = split(/:/, $module_action);
    my $module_name = kebab_to_camel($module_action_arr[0]);
    my $action_name = $module_action_arr[1];
    if (defined $module_name && $module_name eq 'Help') {
        usage();
        return;
    }
    unless (defined $module_name && defined $action_name) {
        Log::error("Invalid command format: module:action");
        usage();
        return;
    }

    my $module_path = "Commands::${module_name}";
    my $module_file = "${module_path}.pm";
    $module_file =~ s/::/\//g;

    # 检查 %INC 哈希表
    unless (exists $INC{$module_file}) {
        eval "require $module_path";
        if ($@) {
            Log::warn("Failed to load module $module_path: $@");
            usage();
            return;
        }
    }
    
    my $module = $module_path->new();
    if ($module->can($action_name)) {
        $module->$action_name(@args);
    }
    else {
        Log::warn("Action $action_name not found in module $module_path");
        usage($module);
    }
}

sub usage
{
    my $module = shift;
    
    print "Usage: $0 <command:action> [args...]\n";

    if (defined $module) {
        $module->usage();
        return;
    }
    
    for my $command (@commands) {
        my $module_name = kebab_to_camel($command->{name});
        my $module_path = "Commands::${module_name}";
        my $module_file = "${module_path}.pm";
        $module_file =~ s/::/\//g;

        # 检查 %INC 哈希表
        unless (exists $INC{$module_file}) {
            eval "require ${module_path}";
            if ($@) {
                Log::error("Failed to load module ${module_path}: $@");
                next;
            }
        }
        my $module = $module_path->new();
        $module->usage();
    }
}

1;